﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management.Automation;

using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.PowerShell;

namespace Mystery.SharePoint.PowerShell
{
	[Cmdlet("Set", "SPMSuperUserAccounts", SupportsShouldProcess = true)]
	[SPCmdlet(RequireUserFarmAdmin = true)]
	class SetSuperUserAccountsCmdlet : SPSetCmdletBase<SPWebApplication>
	{
		[Parameter(Mandatory = true, ValueFromPipeline = true, Position = 0)]
		public SPWebApplicationPipeBind Identity { get; set; }
		/// <summary>
		/// The account to use as the super user account
		/// </summary>
		[Parameter(Mandatory = true)]
		public string SuperUserAccount { get; set; }
		/// <summary>
		/// The account to use as the super reader account
		/// </summary>
		[Parameter(Mandatory = true)]
		public string SuperReaderAccount { get; set; }

		protected override void InternalValidate()
		{
			base.DataObject = this.Identity.Read();

			string poolName = UserUtilites.ExtractDomainUser(base.DataObject.ApplicationPool.ManagedAccount.Username);

			if (poolName.Equals(this.SuperReaderAccount, StringComparison.InvariantCultureIgnoreCase) == true)
			{
				base.ThrowTerminatingError(
					new InvalidOperationException("Super Reader Account cannot equal application pool account"), 
					ErrorCategory.InvalidData, this);
			}
			if (poolName.Equals(this.SuperUserAccount, StringComparison.InvariantCultureIgnoreCase) == true)
			{
				base.ThrowTerminatingError(
					new InvalidOperationException("Super User Account cannot equal application pool account"),
					ErrorCategory.InvalidData, this);
			}
		}

		protected override void UpdateDataObject()
		{
            
            string superAccount = this.SuperUserAccount;
            string readerAccount = this.SuperReaderAccount;
            
            if (base.DataObject.UseClaimsAuthentication == true)
            {
                superAccount = UserUtilites.AddClaimsPrefix(this.SuperUserAccount);
                readerAccount = UserUtilites.AddClaimsPrefix(this.SuperReaderAccount);
            }
            
            string superUser = CreatePolicy(superAccount, SPPolicyRoleType.FullControl);
            string superReader = CreatePolicy(readerAccount, SPPolicyRoleType.FullRead);

            base.Host.UI.WriteLine(string.Format(null, "Setting Portal Super User account: {0}", superAccount));
            base.Host.UI.WriteLine(string.Format(null, "Setting Portal Super Reader account: {0}", readerAccount));
            base.DataObject.Properties.Write("portalsuperuseraccount", superAccount);
            base.DataObject.Properties.Write("portalsuperreaderaccount", readerAccount);
            base.DataObject.Update();
		}

		private string CreatePolicy(string userName, SPPolicyRoleType type)
		{
			SPPolicy policy = Find(userName);

			if (policy == null)
			{
				SPPolicyRole role = base.DataObject.PolicyRoles.GetSpecialRole(type);
				policy = base.DataObject.Policies.Add(userName, null);
				policy.PolicyRoleBindings.Add(role);
			}
            return policy.UserName;
		}

		private SPPolicy Find(string userName)
		{
			foreach (SPPolicy policy in base.DataObject.Policies)
			{
				if (userName.Equals(policy.UserName, StringComparison.InvariantCultureIgnoreCase) == true)
				{
					return policy;
				}
			}
			return null;
		}
	}
}
